<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>🚮 垃圾分类查询 🚮</title>

  <style>
    body {
      width: 90%;
      margin: auto;
    }

    .block {
      display: block;
    }

    .text-center {
      text-align: center;
    }

    .text-uppercase {
      text-transform: uppercase;
    }

    h1 {
      color: #5598df;
      margin: 10% auto;
      font-size: 3em;
      font-family: monospace;
    }

    img {
      width: 100px;
      margin-right: 10px;
    }

    input,
    button {
      outline: 0;
      width: 100%;
      box-sizing: border-box;
      font-size: 32px;
      appearance: none;
      padding: 10px 0;
      margin-top: 10px;
      border: 1px solid #ccc;
      border-radius: 5px;
    }

    button {
      color: white;
      border: none;
      background: #5598df;
    }

    ol#results,
    ul#categories {
      padding: 0;
      margin: 10px auto;
      list-style: none;
    }

    ul#categories li {
      display: flex;
      flex: 1;
      align-items: center;
    }

    ul#categories li h3 {
      margin: 3px;
      font-size: 16px;
    }

    ul#categories li p {
      color: #333;
      margin: 3px;
      font-size: 12px;
    }

    .garbage {
      display: flex;
      line-height: 32px;
      margin: 10px;
      padding: 10px;
      background-color: #eee;
    }

    .garbage-name,
    .garbage-category {
      flex: 1;
    }

    .garbage-category {
      text-align: right;
      padding-right: 10px;
    }

    .category-action::before {
      color:#5598df;
      content: '处置建议: ';
    }

    footer {
      color: #999;
      padding: 50px;
    }
  </style>
</head>
<script id="category" type="text/template">
  <li>
    <div>
      <img src=".#{ img }">
    </div>
    <div>
      <h3>#{name}</h3>
      <p>#{content}</p>
      <p>#{description}</p>
      <p class="category-action" >#{action}</p>
    </div>
  </li>
</script>

<script id="result" type="text/template">
  <li class="garbage" style="color: #{category.color}"  >
      <span class="garbage-name" >#{name}</span>
      <span class="garbage-category" style="background-color: #{category.bgcolor}" >#{category.name}</span>
  </li>
</script>


<script id="report" type="text/template">
  <p class="text-center">没找到想要的结果？</p>
  <a class="block text-center" href="https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzU2NTUyMzQyMQ==&scene=124#wechat_redirect">请提交反馈帮助我们改善数据</a>
</script>

<body>
  <h1 class="text-center text-uppercase">垃圾分类查询</h1>
  <form>
    <input class="input text-center" type="text" name="q">
    <button class="text-center text-uppercase">查询</button>
  </form>
  <ul id="categories"></ul>
  <ol id="results">
  </ol>
  <footer class="text-center">
    <!--<a href="https://github.com/song940/garbage-recycle">Garbage Recycle Project at GitHub.com</a>-->
     &copy; 版权归BabyBox所有 2019
  </footer>
</body>
<script>

  const parseQueryString = () => {
    const querystring = location.search.slice(1);
    return querystring.split('&').reduce((qs, s) => {
      const [name, value] = s.split('=');
      qs[name] = decodeURIComponent(value);
      return qs;
    }, {});
  };

  const parseCSV = str => {
    const lines = str
      .toString()
      .split(/\r?\n/g);
    const [firstLine] = lines;
    const columns = firstLine.split(',');
    return lines
      .slice(1)
      .map(line => line
        .split(',')
        .reduce((o, p, i) => (o[columns[i]] = p, o), {})
      );
  };

  const get = (o, p) => p.split('.').reduce((o, k) => o && o[k], o);

  const render = (id, data) => {
    const template = document.getElementById(id).innerHTML;
    const div = document.createElement('div');
    div.innerHTML = template.replace(/#{([\s\S]*?)}/g, (_, name) => get(data, name.trim()));
    return div;
  }

  const fetchCategories = () =>
    fetch('./data/categories.json')
      .then(res => res.json())
      .then(categories => categories.reduce((o, c) => (o[c.id] = c, o), {}))

  const fetchGarbages = () =>
    fetch('./data/garbage.csv')
      .then(res => res.text())
      .then(parseCSV)


  function compareTwoStrings(first, second) {
    if (!first || !second) return 0;
    first = first.replace(/\s+/g, '')
    second = second.replace(/\s+/g, '')

    if (!first.length && !second.length) return 1;           // if both are empty strings
    if (!first.length || !second.length) return 0;           // if only one is empty string
    if (first === second) return 1;       							     // identical
    if (first.length === 1 && second.length === 1) return 0; // both are 1-letter strings
    if (first.length < 2 || second.length < 2) return 0;     // if either is a 1-letter string

    let firstBigrams = new Map();
    for (let i = 0; i < first.length - 1; i++) {
      const bigram = first.substring(i, i + 2);
      const count = firstBigrams.has(bigram)
        ? firstBigrams.get(bigram) + 1
        : 1;

      firstBigrams.set(bigram, count);
    };

    let intersectionSize = 0;
    for (let i = 0; i < second.length - 1; i++) {
      const bigram = second.substring(i, i + 2);
      const count = firstBigrams.has(bigram)
        ? firstBigrams.get(bigram)
        : 0;

      if (count > 0) {
        firstBigrams.set(bigram, count - 1);
        intersectionSize++;
      }
    }

    return (2.0 * intersectionSize) / (first.length + second.length - 2);
  }


  const { q } = parseQueryString();

  const input = document.querySelector('input')
  const results = document.querySelector('#results');
  const categories = document.querySelector('#categories');

  if (q) {
    input.value = q;
    Promise.all([
      fetchCategories(),
      fetchGarbages()
    ]).then(([categories, garbages]) => {
      garbages
        .map(x => (x.score = compareTwoStrings(x.name, q), x))
        .filter(x => x.score)
        .sort((a, b) => b.score - a.score)
        .forEach(item => {
          item.category = categories[item.sortId];
          results.appendChild(render('result', item));
        });
      results.appendChild(render('report', { query: q }));
    });

  } else {
    fetch('./data/categories.json')
      .then(res => res.json())
      .then(list => {
        list.forEach(item => {
          categories.appendChild(render('category', item));
        });
      })
  }
</script>

  
</html>
